package cz.muni.fi.pa165.musiclibrary.impl.database.dao;

import java.util.List;

import javax.annotation.Nonnull;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.dao.DataAccessException;
import org.springframework.stereotype.Repository;

import cz.muni.fi.pa165.musiclibrary.impl.database.entity.IAlbum;
import cz.muni.fi.pa165.musiclibrary.impl.database.entity.Album;

/**
 *
 * @author Maros Kucbel
 * @date 2012-10-11T18:02:42+0200
 */
@Repository
public class AlbumDAO extends AbstractDAO implements IAlbumDAO {
    /**
     * Factory for creating {@link EntityManager}.
     */    
    private EntityManager entityManager;
    
    /**
     * Injects {@link EntityManager} instance
     */
    @PersistenceContext
    @Required
    @Override
    public void setEntityManager(EntityManager entityManager) {
        this.entityManager = entityManager;
    }
    
    @Override
    public void create(@Nonnull final IAlbum album) throws DataAccessException {
        Validate.isTrue(album != null, "Album should not be null.");
        Validate.isTrue(album.getIdAlbum() == null, "Album identifier should be null.");
        
        entityManager.persist(album);

    }

    @Override
    public void update(@Nonnull final IAlbum album) throws DataAccessException {
        Validate.isTrue(album != null, "Album should not be null.");
        Validate.isTrue(album.getIdAlbum() != null, "Album identifier should not be null.");
        final Query update = entityManager.createQuery("UPDATE Album a SET a.title = :title, "
                + "a.releaseDate = :releaseDate, a.albumArt = :albumArt WHERE a.idAlbum = :idAlbum");
        update.setParameter("title", album.getTitle())//
                .setParameter("releaseDate", album.getReleaseDate())//
                .setParameter("albumArt", album.getAlbumArt())//
                .setParameter("idAlbum", album.getIdAlbum());
        update.executeUpdate();
    }

    @Override
    public void delete(@Nonnull final IAlbum album) throws DataAccessException {
        Validate.isTrue(album != null, "Album should not be null.");
        Validate.isTrue(album.getIdAlbum() != null, "Album identifier should not be null.");
        final Query delete = entityManager.createQuery("DELETE FROM Album a WHERE a.idAlbum = :idAlbum");
        delete.setParameter("idAlbum", album.getIdAlbum());
        delete.executeUpdate();
    }

    @Override
    public IAlbum getById(@Nonnull final Long id) throws DataAccessException {
        Validate.isTrue(id != null, "Identifier should not be null.");
        final Album album = entityManager.find(Album.class, id);
        return album;
    }

    @Override
    public List<IAlbum> getAll() throws DataAccessException {
        final List<IAlbum> albums = entityManager.createQuery("SELECT a FROM Album a").getResultList();
        return albums;
    }

    @Override
    public List<IAlbum> getByTitle(@Nonnull final String title) throws DataAccessException {
        Validate.isTrue(StringUtils.isNotBlank(title), "String to search for should not be null or empty.");
        final Query get = entityManager.createQuery("SELECT a FROM Album a WHERE LOWER(a.title) LIKE :title");
        get.setParameter("title", "%" + title.toLowerCase() + "%");
        final List<IAlbum> albums = get.getResultList();
        return albums;
    }

    @Override
    public List<IAlbum> getByReleaseDate(@Nonnull final LocalDate date) throws DataAccessException {
        Validate.isTrue(date != null, "Date should not be null.");
        final Query get = entityManager.createQuery("SELECT a FROM Album a WHERE a.releaseDate = :date");
        get.setParameter("date", date);
        final List<IAlbum> albums = get.getResultList();
        return albums;
    }

}